#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QSet>
#include <QSettings>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QTextStream>
#include <QtConcurrent>
#include "qtvplugin_orbit.h"
#include "ui_qtvplugin_orbit.h"
#include "../geocalc/geocalc.h"
// "coreLib.h" includes basic types from the core library,
// such as cSite, cJulian, etc. The header file also contains a
// "using namespace" statement for Zeptomoby::OrbitTools.
#include "coreLib.h"

// "orbitLib.h" includes basic types from the orbit library,
// including cOrbit.
#include "orbitLib.h"

void qtvplugin_orbit::init_trace_mod()
{
#if QT_VERSION <= 0x060600
	connect (&m_watcher,&QFutureWatcher<void>::finished,this, &qtvplugin_orbit::slot_cal_finished,Qt::QueuedConnection);
#endif
	m_pTraceMod = new QSqlQueryModel;
	ui->tableView_orbit_trace->setModel(m_pTraceMod);
	m_pSatPosSpeedMod = new QStandardItemModel(this);
	m_pSatPosSpeedMod->setColumnCount(10);
	m_pSatPosSpeedMod->setHeaderData(0, Qt::Horizontal, tr("enabled"));
	m_pSatPosSpeedMod->setHeaderData(1, Qt::Horizontal, tr("sname"));
	m_pSatPosSpeedMod->setHeaderData(2, Qt::Horizontal, tr("sid"));
	m_pSatPosSpeedMod->setHeaderData(3, Qt::Horizontal, "lat");
	m_pSatPosSpeedMod->setHeaderData(4, Qt::Horizontal, "lon");
	m_pSatPosSpeedMod->setHeaderData(5, Qt::Horizontal, "alt");
	m_pSatPosSpeedMod->setHeaderData(6, Qt::Horizontal, tr("Az"));
	m_pSatPosSpeedMod->setHeaderData(7, Qt::Horizontal, tr("El"));
	m_pSatPosSpeedMod->setHeaderData(8, Qt::Horizontal, tr("Dis(m)"));
	m_pSatPosSpeedMod->setHeaderData(9, Qt::Horizontal, tr("Radial Speed(m/s)"));

	ui->tableView_orbit_trace_pos->setModel(m_pSatPosSpeedMod);

	//Draw Covering Polygon .
	for (double beta = 0.5; beta <360.5; beta += 1)
		m_trace_beta .push_back(beta);

	confirm_trace_conn(true);
}
void qtvplugin_orbit::on_checkBox_track_clicked()
{
	save_ini();
}


void qtvplugin_orbit::on_dateTimeEdit_orbit_time_dateTimeChanged(const QDateTime &dateTime)
{
	m_needUpdate = true;
}



void qtvplugin_orbit::on_pushButton_orbit_track_remove_clicked()
{
	save_ini();
	auto rows = ui->tableView_orbit_trace->selectionModel()->selectedRows();
	QSet<QString>	namesToBeRemoved;
	foreach (auto v, rows)
	{
		QString sname = m_pTraceMod->data(m_pTraceMod->index(v.row(), 0)).toString();
		namesToBeRemoved << sname;
	}
	if (!confirm_trace_conn(false))
		return;
	const QString dbname = ini_file();
	QSqlDatabase db = QSqlDatabase::database(dbname);
	QSqlQuery query(db);
	try
	{
		QString querySql = "DELETE from trace where t_sname = ?; ";
		foreach (QString sname, namesToBeRemoved)
		{
			if (!query.prepare(querySql))
				throw query.lastError().text();
			query.addBindValue(sname);
			if (!query.exec())
				throw query.lastError().text();
		}
	}
	catch (QString msg)
	{
		QMessageBox::warning(this, tr("dberror"), msg);
	}
	confirm_trace_conn(true);
	m_needUpdate = true;
}

bool qtvplugin_orbit::confirm_trace_conn(bool reset_gui)
{
	try
	{
		QDateTime dtmUTC = ui->dateTimeEdit_orbit_time->dateTime();
		time_t utcT = dtmUTC.toSecsSinceEpoch();
		const QString dbname = ini_file();
		if (QSqlDatabase::contains(dbname))
		{
			QSqlDatabase db = QSqlDatabase::database(dbname);
			if (db.isValid())
			{
				QSqlQuery q(db);
				QString testSql = "SELECT t_sname FROM trace WHERE "
								  "t_sname = '000'; ";
				if (!reset_gui)
				{
					if (q.exec(testSql))
						return true;
				}
				QString cond = ui->lineEdit_orbit_trace_filter->text();
				/*
				 * Using PARTITION RANK to Select nearest epoch from database:
					 WITH srk_1 AS ( select t_sname, sid, sepoch ,stime, sformat ,stext, RANK() OVER (PARTITION BY t_sname ORDER BY abs(sepoch - UTC) ASC) as stank from trace left join tle on trace.t_sname = tle.sname)
					 SELECT t_sname, sid, sepoch ,stime, sformat ,stext, (UTC - sepoch)/3600.0/24.0 as age_days  from srk_1 where stank  = 1
				*/
				QString querySql = QString("WITH srk_1 AS ( select t_sname, sid, sepoch ,stime, sformat ,stext, "
										   "RANK() OVER (PARTITION BY t_sname ORDER BY abs(sepoch - %1) ASC) as stank "
										   " from trace left join tle on trace.t_sname = tle.sname) ")
									   .arg(utcT)
								   + " SELECT "
								   + " t_sname as '" + tr("sname") + "'"
								   + ", sid as '" + tr("sid") + "'"
								   + ", sepoch as '" + tr("sepoch") + "'"
								   + ", stime as '" + tr("stime") + "'"
								   + ", sformat as '" + tr("sformat") + "'"
								   + QString(", (%1 - sepoch)/3600.0/24.0 as '").arg(utcT) + tr("age_days") + "'"
								   + ", stext as '" + tr("stext") + "'"
								   + QString("  from srk_1 where stank  = 1 and  (t_sname like '%%1%' OR sid like '%%1%') order by t_sname asc ")
										 .arg(cond);
				//qDebug()<<querySql;
				if (q.exec(querySql))
				{
					m_pTraceMod->setQuery(std::move(q));
					return true;
				}
				db.close();
			}
			//FAILED
			QSqlDatabase::removeDatabase(dbname);
		}
		QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", dbname);
		if (!db.isValid())
			throw db.lastError().text();
		QDir dir_app(QCoreApplication::applicationDirPath());
		QString fileName = ui->lineEdit_orbit_tle_db->text();
		fileName = dir_app.absoluteFilePath(fileName);
		db.setDatabaseName(fileName);
		if (!db.open())
			throw db.lastError().text();
		//Check table
		QString testSql
			=  "SELECT t_sname FROM trace WHERE "
			  "t_sname = '000'; ";
		QSqlQuery q(db);
		if (!q.exec(testSql))
		{
			QString drop_tbsql = " DROP TABLE trace ;";
			q.exec(drop_tbsql);
			QString create_tbsql = " CREATE TABLE IF NOT EXISTS trace ( "
								   " t_sname TEXT, "
								   " PRIMARY KEY (t_sname) "
								   " );";
			if (!q.exec(create_tbsql))
				throw q.lastError().text();
		}
		if (reset_gui)
		{
			QString cond = ui->lineEdit_orbit_tledb_filter->text();
			/*
				 * Using PARTITION RANK to Select nearest epoch from database:
					 WITH srk_1 AS ( select t_sname, sid, sepoch ,stime, sformat ,stext, RANK() OVER (PARTITION BY t_sname ORDER BY abs(sepoch - UTC) ASC) as stank from trace left join tle on trace.t_sname = tle.sname)
					 SELECT t_sname, sid, sepoch ,stime, sformat ,stext, (UTC - sepoch)/3600.0/24.0 as age_days  from srk_1 where stank  = 1
				*/
			QString querySql = QString("WITH srk_1 AS ( select t_sname, sid, sepoch ,stime, sformat ,stext, "
									   "RANK() OVER (PARTITION BY t_sname ORDER BY abs(sepoch - %1) ASC) as stank "
									   " from trace left join tle on trace.t_sname = tle.sname) ")
								   .arg(utcT)
							   + " SELECT "
							   + " t_sname as '" + tr("sname") + "'"
							   + ", sid as '" + tr("sid") + "'"
							   + ", sepoch as '" + tr("sepoch") + "'"
							   + ", stime as '" + tr("stime") + "'"
							   + ", sformat as '" + tr("sformat") + "'"
							   + QString(", (%1 - sepoch)/3600.0/24.0 as '").arg(utcT) + tr("age_days") + "'"
							   + ", stext as '" + tr("stext") + "'"
							   + QString("  from srk_1 where stank  = 1 and  (t_sname like '%%1%' OR sid like '%%1%') order by t_sname asc ")
									 .arg(cond);
			if (q.exec(querySql))
				m_pTraceMod->setQuery(std::move(q));
			else
				throw q.lastError().text();
		}
	}
	catch (QString msg)
	{
		QMessageBox::warning(this, tr("dberror"), msg);
		return false;
	}

	return true;
}

void qtvplugin_orbit::on_pushButton_orbit_trace_find_clicked()
{
	save_ini();
	confirm_trace_conn(true);
}

void qtvplugin_orbit::cal_sat_pv()
{
	try
	{
		const QDateTime dtmUTC = ui->dateTimeEdit_orbit_time->dateTime();
		const time_t utcT = dtmUTC.toSecsSinceEpoch();
		const int minEL = ui->spinBox_minEL->value();
		const double ob_lat = ui->doubleSpinBox_orbit_ob_lat->value();
		const double ob_lon = ui->doubleSpinBox_orbit_ob_lon->value();
		const double ob_alt = ui->doubleSpinBox_orbit_ob_alt->value();
		const int max_age_days = ui->spinBox_orbit_maxAge->value();
		const QString dbname = ini_file();
		if (QSqlDatabase::contains(dbname))
		{
			QSqlDatabase db = QSqlDatabase::database(dbname);
			QSqlQuery q(db);
			QString querySql = QString("WITH srk_1 AS ( select t_sname, sid, sepoch ,stime, sformat ,stext, "
									   "RANK() OVER (PARTITION BY t_sname ORDER BY abs(sepoch - %1) ASC) as stank "
									   " from trace left join tle on trace.t_sname = tle.sname) ")
								   .arg(utcT)
							   + " SELECT "
							   + " t_sname as '" + tr("sname") + "'"
							   + ", sid as '" + tr("sid") + "'"
							   + ", sepoch as '" + tr("sepoch") + "'"
							   + ", stime as '" + tr("stime") + "'"
							   + ", sformat as '" + tr("sformat") + "'"
							   + QString(", (%1 - sepoch)/3600.0/24.0 as '").arg(utcT) + tr("age_days") + "'"
							   + ", stext as '" + tr("stext") + "'"
							   + QString("  from srk_1 where stank  = 1 order by t_sname asc ") ;
			if (!q.exec(querySql))
				throw q.lastError().text();
			using namespace  CES_GEOCALC;

			m_tasks_trace.clear();
			while (q.next())
			{
				tag_trace_task t;
				t.nUTC = utcT;
				t.sname = q.value(0).toString();
				t.sid =   q.value(1).toString();
				const QString stext = q.value(6).toString();
				const QStringList lstTLE = stext.split("|");
				t.strname = t.sname.toStdString();
				t.line1 = lstTLE.at(1).toStdString();
				t.line2 = lstTLE.at(2).toStdString();
				t.minEL = minEL;
				t.age_days = q.value(5).toDouble();
				t.ob_lla[0] = ob_lat;
				t.ob_lla[1] = ob_lon;
				t.ob_lla[2] = ob_alt;
				t.max_age_days = max_age_days;
				m_tasks_trace << t;
			}
			//Turn tracing true
			m_bool_trace_caling = true;
			//Using Multi thread pooling with Qt Concurrent.
#if QT_VERSION <= 0x060600
			m_future_trace =QtConcurrent::map(
								 m_tasks_trace.begin(),
								 m_tasks_trace.end(),
								 std::bind(&qtvplugin_orbit::cal_trace,
										   this,std::placeholders::_1));
			m_watcher.setFuture(m_future_trace);
#else
			m_future_trace =QtConcurrent::map(
								 m_tasks_trace.begin(),
								 m_tasks_trace.end(),
								 std::bind(&qtvplugin_orbit::cal_trace,
										   this,std::placeholders::_1))
								 .then(this,std::bind(&qtvplugin_orbit::disp_trace,this));
#endif
		}
	}
	catch (QString msg)
	{
		QMessageBox::warning(this, tr("dberror"), msg);
	}
}

#if QT_VERSION <= 0x060600
void qtvplugin_orbit::slot_cal_finished()
{
	disp_trace();
}
#endif

void qtvplugin_orbit::cal_trace(tag_trace_task & t)
{
	if (fabs(t.age_days) > t.max_age_days)
	{
		t.valid = false;
		t.el = -90;
		t.az = 0;
		return;
	}
	using namespace  CES_GEOCALC;
	Zeptomoby::OrbitTools::cTle tle(t.strname,
									t.line1,
									t.line2);
	cSatellite sat(tle);
	cJulian jd(t.nUTC);
	cEciTime eci = sat.PositionEci(jd);
	cGeoTime geo(eci);
	//Cal Sat LLA
	t.lla[0] = geo.LatitudeDeg();
	t.lla[1] = warp_to_180(geo.LongitudeDeg());
	t.lla[2] = geo.AltitudeKm()*1000;
	//Observe
	cSite site(t.ob_lla[0],t.ob_lla[1],t.ob_lla[2]/1000.0);
	cTopo lookAngle = site.GetLookAngle(eci);
	//Look Angle and Range Speed( for further Freq payback )
	t.az = lookAngle.AzimuthDeg();
	t.el = lookAngle.ElevationDeg();
	t.dis = lookAngle.RangeKm() * 1000;
	t.speed = lookAngle.RangeRateKmSec()*1000;

	//Cal contours
	contour_elevation(
		t.lla
		,t.minEL
		,0
		,m_trace_beta
		,&t.vec_lat
		,&t.vec_lon
		,&t.vec_D
		,&t.vec_Az
		,&t.vec_El,
		true,1);

	t.valid = true;
}

void qtvplugin_orbit::disp_trace()
{
	QString cond = ui->lineEdit_orbit_trace_filter->text();
	const int rowCnt = m_pSatPosSpeedMod->rowCount();
	const int nCnt = m_tasks_trace.size();
	int nRow = 0;
	for(auto p = m_markTraceNames.begin();p!=m_markTraceNames.end();++p)
		p.value() = false;
	int broadcasted = 0;
	for (int i = 0;i<nCnt;++i)
	{
		tag_trace_task & t = m_tasks_trace[i];
		bool needBroadcast = false;
		if (cond.length())
		{
			if ((!t.sname.contains(cond) )&&(!t.sid.contains(cond)))
				continue;
		}
		if (nRow >= rowCnt)
		{
			if (t.valid)
			{
				m_pSatPosSpeedMod->appendRow(new QStandardItem(tr("YES")));
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,0),true,Qt::CheckStateRole);
			}
			else
			{
				//TLE too old
				m_pSatPosSpeedMod->appendRow(new QStandardItem(tr("OUTDATED")));
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,0),true,Qt::CheckStateRole);
			}
		}
		else
		{
			bool check = m_pSatPosSpeedMod->data(m_pSatPosSpeedMod->index(nRow,0),Qt::CheckStateRole).toBool();
			if (t.valid)
			{
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 0),
										   check ? tr("YES") : tr("NO"));
				needBroadcast = check;
			}
			else
			{
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 0),
										   tr("OUTDATED"));
			}
		}
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,1),t.sname);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,2),t.sid);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,3),t.lla[0]);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,4),t.lla[1]);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,5),t.lla[2]);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,6),t.az);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,7),t.el);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,8),t.dis);
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow,9),t.speed);

		if (!t.valid)
		{
			m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 0),
									   QColor(192, 0, 0),
									   Qt::BackgroundRole);
			m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 7),
									   QColor(192, 0, 0),
									   Qt::BackgroundRole);
		}
		else
		{
			if (t.el >= t.minEL)
			{
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 0),
										   QColor(0, 192, 0),
										   Qt::BackgroundRole);
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 7),
										   QColor(0, 192, 0),
										   Qt::BackgroundRole);
			}
			else
			{
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 0),
										   QColor(255, 255, 0),
										   Qt::BackgroundRole);
				m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(nRow, 7),
										   QColor(255, 255, 0),
										   Qt::BackgroundRole);
			}
		}

		++nRow;
		//Paint to Map
		if (t.valid)
		{
			m_markTraceNames[t.sname] = true;
			update_trace_map(t);
			if (t.el >= t.minEL && needBroadcast && !broadcasted)
			{
				++broadcasted;
				//report
				report_trace_evt(t);
			}
		}
	}
	fini_trace_map();
	int delRows = rowCnt - nRow;
	if (delRows>0)
		m_pSatPosSpeedMod->removeRows(nRow,delRows);
	//Tracing finished.
	m_bool_trace_caling = false;
}

void qtvplugin_orbit::fini_trace_map()
{
	QString strMarkerName = "geomarker";
	layer_interface * pif =  m_pVi->layer(strMarkerName);
	QMap<QString, QVariant> inPara, outPara;
	inPara["function"] = "delete_marks";
	int nM = 0;
	for(auto p = m_markTraceNames.begin();p!=m_markTraceNames.end();++p)
	{
		if (p.value() == false)
		{
			inPara[QString("name%1").arg(nM)] = "SAT_"+p.key();
			++nM;
			inPara[QString("name%1").arg(nM)] = "COVER_"+p.key();
			++nM;
			inPara[QString("name%1").arg(nM)] = "LINE_"+p.key();
			++nM;
		}
	}
	if (nM)
		pif->call_func(inPara);
	//! Observer
	inPara.clear();
	inPara["function"] = "update_point";
	inPara["name"] = "OBSERVER";
	inPara["lat"] = ui->doubleSpinBox_orbit_ob_lat->value();
	inPara["lon"] = ui->doubleSpinBox_orbit_ob_lon->value();
	inPara["width"] = 7;
	inPara["height"] = 7;
	inPara["color_pen"] = QString("0,0,0,200");
	inPara["color_label"]  = QString("0,0,0,200");
	pif->call_func(inPara);

	inPara.clear();
	inPara["function"] = "update_props";
	inPara["name"] = "OBSERVER";
	inPara["LABEL"] = tr("OBSERVER");
	pif->call_func(inPara);
}
void qtvplugin_orbit::report_trace_evt(tag_trace_task & t)
{
	if (!t.valid)
		return;
	QMap<QString, QVariant > map_evt;
	map_evt["source"] = get_name();
	map_evt["destin"] = "ALL";
	map_evt["name"] = "orbit";
	map_evt["sname"] = t.sname;
	map_evt["sid"] = t.sid;
	map_evt["az"] = t.az;
	map_evt["el"] = t.el;
	map_evt["range"] = t.dis;
	map_evt["speed"] = t.speed;
	map_evt["lat"] = t.lla[0];
	map_evt["lon"] = t.lla[1];
	map_evt["alt"] = t.lla[2];
	map_evt["ob_lat"] = t.ob_lla[0];
	map_evt["ob_lon"] = t.ob_lla[1];
	map_evt["ob_alt"] = t.ob_lla[2];
	map_evt["utc"] = (long long)t.nUTC;
	map_evt["minel"] = t.minEL;
	m_pVi->post_event(map_evt);
}
void qtvplugin_orbit::update_trace_map(tag_trace_task & t)
{
	if (!m_pVi)
		return;
	QString strMarkerName = "geomarker";
	layer_interface * pif =  m_pVi->layer(strMarkerName);
	QMap<QString, QVariant> inPara, outPara;
	//! 1. Draw Cover
	inPara["function"] = "update_polygon";
	inPara["name"] = QString("COVER_%1").arg(t.sname);
	inPara["type"] = 6;
	inPara["width_pen"] = 2;
	inPara["style_pen"] = 1;
	quint64 hash_v = qHash(t.sname) % 128;
	inPara["color_pen"] = QString("%1,%2,%3,128")
							  .arg(hash_v *137 % 192)
							  .arg(hash_v *219 % 192)
							  .arg(hash_v *73 % 192);
	const int points = t.vec_lat.size();
	for (int i=0;i<points;++i)
	{
		inPara[QString("lat%1").arg(i)] = t.vec_lat[i];
		inPara[QString("lon%1").arg(i)] = t.vec_lon[i];
	}
	inPara[QString("lat%1").arg(points)] = t.vec_lat[0];
	inPara[QString("lon%1").arg(points)] = t.vec_lon[0];
	pif->call_func(inPara);

	//! 2.1. draw Center SAT
	inPara.clear();
	inPara["function"] = "update_point";
	inPara["name"] = QString("SAT_%1").arg(t.sname);
	inPara["LABEL"] = t.sname.trimmed();
	inPara["lat"] = t.lla[0];
	inPara["lon"] = t.lla[1];
	inPara["width"] = 5;
	inPara["height"] = 5;
	inPara["color_pen"] = QString("%1,%2,%3,128")
							  .arg(hash_v *137 % 192)
							  .arg(hash_v *219 % 192)
							  .arg(hash_v *73 % 192);
	inPara["color_label"]  = QString("%1,%2,%3,224")
								.arg((hash_v *137 % 192)/3)
								.arg((hash_v *219 % 192)/3)
								.arg((hash_v *73 % 192)/3);
	pif->call_func(inPara);
	//!2.2 Update Sat props, names
	inPara.clear();
	inPara["function"] = "update_props";
	inPara["name"] = QString("SAT_%1").arg(t.sname);
	inPara["LABEL"] = t.sname.trimmed();
	inPara["lat"] = t.lla[0];
	inPara["lon"] = t.lla[1];
	inPara["alt"] = t.lla[2];
	pif->call_func(inPara);

	//3.1 Draw Observe Lines
	if (t.el>=t.minEL)
	{
		inPara.clear();
		inPara["function"] = "update_line";
		inPara["name"] =  QString("LINE_%1").arg(t.sname);
		inPara["LABEL"] = "Observer";
		inPara["lat0"] = t.ob_lla[0];
		inPara["lon0"] = t.ob_lla[1];
		inPara["lat1"] = t.lla[0];
		inPara["lon1"] = t.lla[1];
		inPara["color_pen"] = QString("%1,%2,%3,128")
								  .arg(hash_v *137 % 192)
								  .arg(hash_v *219 % 192)
								  .arg(hash_v *73 % 192);
		inPara["width_pen"] = 1;
		inPara["style_pen"] = 1;
		pif->call_func(inPara);

		//3.2 Observe range
		inPara.clear();
		inPara["function"] = "update_props";
		inPara["name"] = QString("LINE_%1").arg(t.sname);
		inPara["LABEL"] = QString("Az %1 El %2").arg(t.az,0,'f',1).arg(t.el,0,'f',1);
		inPara["lat"] = t.lla[0];
		inPara["lon"] = t.lla[1];
		inPara["alt"] = t.lla[2];
		pif->call_func(inPara);
	}
	else
	{
		inPara["function"] = "delete_marks";
		inPara[QString("name0")] =QString("LINE_%1").arg(t.sname);
		pif->call_func(inPara);
	}

}


void qtvplugin_orbit::qtvplugin_orbit::on_pushButton_orbit_ob_getpos_clicked()
{
	double clat,clon;
	m_pVi->centerLLA(&clat,&clon);
	ui->doubleSpinBox_orbit_ob_lat->setValue(clat);
	ui->doubleSpinBox_orbit_ob_lon->setValue(clon);
	save_ini();
}



void qtvplugin_orbit::on_tableView_orbit_trace_pos_clicked(const QModelIndex &index)
{
	QModelIndex idx = m_pSatPosSpeedMod->index(index.row(),0);
	if (index.column()==0)
	{
		bool check = m_pSatPosSpeedMod->data(idx,Qt::CheckStateRole).toBool();
		m_pSatPosSpeedMod->setData(m_pSatPosSpeedMod->index(index.row(),0),!check,Qt::CheckStateRole);
	}
}

